#ifndef  __PORT_TIMER_H__
#define  __PORT_TIMER_H__ 


#include "suniv.h"
#include <types.h>
#include <io.h>


#define   TIMER_IRQ_EN_OFFSET            (0)
#define   TIMER_CTRLX_OFFSET(timer_x)    (0x10 + ((timer_x) * 0x10))
#define   TIMER_INTVX_OFFSET(timer_x)    (0x14 + ((timer_x) * 0x10))
#define   TIMER_CURX_OFFSET(timer_x)     (0x18 + ((timer_x) * 0x10))

static inline void timer_init(uint8_t timer_x, uint8_t mode, uint8_t clk_src, uint8_t psc) 
{
    uint32_t val = (mode << 7) | (psc << 4) | (clk_src << 2);
    write32(TIMER_REG_BASE + TIMER_CTRLX_OFFSET(timer_x), val);
}


static inline void timer_set_period(uint8_t timer_x, uint32_t val)
{
    write32(TIMER_REG_BASE + TIMER_INTVX_OFFSET(timer_x), val);
}


static inline uint32_t timer_get_cnt(uint8_t timer_x)
{
    return read32(TIMER_REG_BASE + TIMER_CURX_OFFSET(timer_x));
}


static inline void timer_set_cnt(uint8_t timer_x, uint32_t val)
{
    write32(TIMER_REG_BASE + TIMER_CURX_OFFSET(timer_x), val);
}


static inline void timer_start(uint8_t timer_x)
{
    uint32_t reg = TIMER_REG_BASE + TIMER_CTRLX_OFFSET(timer_x);
    write32(reg, (read32(reg) | (1 << 0) | (1 << 1)));
}


static inline void timer_stop(uint8_t timer_x)
{
    uint32_t reg = TIMER_REG_BASE + TIMER_CTRLX_OFFSET(timer_x);
    write32(reg, (read32(reg) & ~(1 << 0)));
}


static inline void timer_int_enable(uint8_t timer_x)
{
    write32(TIMER_REG_BASE + TIMER_IRQ_EN_OFFSET, (read32(TIMER_REG_BASE + TIMER_IRQ_EN_OFFSET) | (1 << timer_x)));
}


static inline void timer_int_disable(uint8_t timer_x)
{
    write32(TIMER_REG_BASE + TIMER_IRQ_EN_OFFSET, (read32(TIMER_REG_BASE + TIMER_IRQ_EN_OFFSET) & ~(1 << timer_x)));
}


static inline void timer_pending_clear(uint8_t timer_x)
{
    write32((0x01C20C00) + 0x04, (1 << timer_x));
}


#endif // __PORT_TIMER_H__